import relog as rl
import json
import os
import re
from collections import defaultdict
from core import CraftingHelperCore

# 全局变量
_data = []
_base_materials = set()
_id_to_name = {}
_all_item_ids = set()
_crafting_helper = None

class _DataLoader:
    """内部数据加载器类，使用单例模式确保数据只加载一次"""
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(_DataLoader, cls).__new__(cls)
            cls._instance._initialized = False
        return cls._instance
    
    def __init__(self):
        if not self._initialized:
            self._initialized = True
            self.load_data()
    
    def load_data(self):
        """加载所有数据"""
        global _data, _base_materials, _id_to_name, _all_item_ids, _crafting_helper
        
        rl.write("sra.log", "data_loader:正在加载物品数据...")
        try:
            with open('items.json', 'r', encoding='utf-8') as f:
                _data = json.load(f)
            rl.write("sra.log", f"data_loader:已加载 {len(_data)} 个物品数据")
        except Exception as e:
            rl.write("sra.log", f"data_loader:加载物品数据失败: {str(e)}")
            _data = []
        
        # 加载基础材料
        _base_materials = self._load_base_materials()
        
        # 构建名称映射
        _id_to_name = self._build_name_map()
        
        # 创建所有物品ID的集合
        _all_item_ids = {item["id"] for item in _data} if _data else set()
        rl.write("sra.log", f"data_loader:已创建物品ID集合,包含 {len(_all_item_ids)} 个唯一ID")
        
        # 初始化合成助手
        self._initialize_global_crafting_helper()
        
        return _data, _base_materials, _id_to_name, _all_item_ids
    
    def _load_base_materials(self):
        """加载基础材料名单"""
        global _base_materials
        
        base_materials_file = "base_materials.json"
        rl.write("sra.log", f"data_loader:尝试加载基础材料名单: {base_materials_file}")
        base_materials = set()
        
        try:
            if os.path.exists(base_materials_file):
                with open(base_materials_file, "r", encoding="utf-8") as f:
                    base_materials = set(json.load(f))
                rl.write("sra.log", f"data_loader:已加载基础材料名单，包含 {len(base_materials)} 个材料")
            else:
                # 创建默认的基础材料名单
                default_base_materials = [
                    "IRON_DUST", "GOLD_DUST", "COPPER_DUST",
                    "TIN_DUST", "LEAD_DUST", "SILVER_DUST",
                    "ALUMINUM_DUST", "ZINC_DUST", "MAGNESIUM_DUST",
                    "BUCKET_OF_OIL", "SULFATE", "SLIME_BALL", "BORAX", "NETHER_ICE",
                    "VEX_GEM", "BASIC_CIRCUIT_BOARD", "GHOSTLY_ESSENCE", "STARDUST_METEOR",
                    "SEGGANESSON", "OSMIUM_DUST", "ARSENIC", "TINY_URANIUM",
                    "LANTHANUM_INGOT", "NEODYMIUM_INGOT", "GADOLINIUM_INGOT",
                    "TERBIUM_INGOT", "DYSPROSIUM_INGOT", "HOLMIUM_INGOT",
                    "ERBIUM_INGOT", "YTTERBIUM_INGOT", "MONAZITE",
                    "QUIRP_UP", "QUIRP_DOWN", "QUIRP_LEFT", "QUIRP_RIGHT", "QUIRPCONDENSATE",
                    "ZOT_UP_2", "ZOT_DOWN_2", "ZOT_LEFT_2", "ZOT_RIGHT_2", "TE_INFO",
                    "MOON_DUST", "MOON_ROCK", "MARS_DUST", "MARS_ROCK", "FALLEN_METEOR",
                    "DRY_ICE", "METHANE_ICE", "SULFUR_BLOCK", "VENTSTONE", "LASERITE_ORE",
                    "MOON_CHEESE", "BROKEN_SOLAR_PANEL_RELIC", "FALLEN_SATELLITE_RELIC"
                ]
                with open(base_materials_file, "w", encoding="utf-8") as f:
                    json.dump(default_base_materials, f, indent=2)
                base_materials = set(default_base_materials)
                rl.write("sra.log", f"data_loader:已创建默认基础材料名单，包含 {len(base_materials)} 个材料")
        except Exception as e:
            rl.write("sra.log", f"data_loader:加载基础材料名单时出错: {str(e)}")
            base_materials = set()
        
        return base_materials
    
    def save_base_materials(self, new_materials):
        """保存基础材料名单到文件"""
        global _base_materials
        
        try:
            with open("base_materials.json", "w", encoding="utf-8") as f:
                json.dump(sorted(new_materials), f, indent=2, ensure_ascii=False)
            _base_materials = set(new_materials)
            rl.write("sra.log", f"data_loader:基础材料名单已更新，包含 {len(_base_materials)} 个材料")
            return True, None
        except Exception as e:
            rl.write("sra.log", f"data_loader:保存基础材料名单失败: {str(e)}")
            return False, str(e)
    
    def get_base_materials(self):
        """获取当前基础材料名单"""
        global _base_materials
        return _base_materials.copy()
    
    def validate_material_ids(self, material_ids):
        """验证材料ID是否有效"""
        global _all_item_ids
        
        valid_ids = []
        invalid_ids = []
        
        for mat_id in material_ids:
            if mat_id in _all_item_ids:
                valid_ids.append(mat_id)
            else:
                invalid_ids.append(mat_id)
        
        rl.write("sra.log", f"data_loader:验证材料ID - 有效: {len(valid_ids)}, 无效: {len(invalid_ids)}")
        return valid_ids, invalid_ids
    
    def _build_name_map(self):
        """构建名称映射并保存到文件（遵循先来后到原则）"""
        global _data, _id_to_name
        
        name_map_file = "name_map.json"
        rl.write("sra.log", f"data_loader:正在处理名称映射，使用文件: {name_map_file}")
        name_map = {}
        
        # 如果没有物品数据，返回空映射
        if not _data:
            rl.write("sra.log", "data_loader:警告: 无物品数据，无法构建名称映射")
            return name_map
        
        # 尝试加载现有映射
        try:
            if os.path.exists(name_map_file):
                with open(name_map_file, "r", encoding="utf-8") as f:
                    name_map = json.load(f)
                rl.write("sra.log", f"data_loader:已从文件加载名称映射，包含 {len(name_map)} 个条目")
                return name_map
        except Exception as e:
            rl.write("sra.log", f"data_loader:加载名称映射时出错: {str(e)}")
        
        # 构建新映射
        rl.write("sra.log", "data_loader:构建名称映射（先来后到原则）...")
        
        # 遍历所有物品（按照数据中的顺序）
        for item in _data:
            item_id = item["id"]
            
            # 如果物品ID尚未在映射中，添加它
            if item_id not in name_map:
                name_map[item_id] = item["name"]
            
            # 遍历物品的配方（按照配方中的顺序）
            if "recipe" in item and item["recipe"]:
                for slot in item["recipe"]:
                    if slot and isinstance(slot, dict):
                        material_id = slot["material"]
                        
                        # 如果材料ID尚未在映射中，添加它
                        if material_id not in name_map:
                            name_map[material_id] = slot["name"]
        
        # 保存到文件
        try:
            with open(name_map_file, "w", encoding="utf-8") as f:
                json.dump(name_map, f, ensure_ascii=False, indent=2)
            rl.write("sra.log", f"data_loader:名称映射构建完成，包含 {len(name_map)} 个条目")
        except Exception as e:
            rl.write("sra.log", f"data_loader:保存名称映射时出错: {str(e)}")
        
        return name_map
    
    def _initialize_global_crafting_helper(self):
        """初始化全局合成助手"""
        global _data, _crafting_helper
        
        if _crafting_helper is not None:
            rl.write("sra.log", "data_loader:合成助手已初始化，跳过")
            return
        
        rl.write("sra.log", "data_loader:正在初始化全局合成助手...")
        
        try:
            # 直接从items.json构建合成表
            craft_table = {}
            
            # 如果没有数据，返回空助手
            if not _data:
                rl.write("sra.log", "data_loader:警告: 无物品数据，无法初始化合成助手")
                _crafting_helper = None
                return None
            
            for item in _data:
                item_id = item["id"]
                
                # 跳过没有配方的物品
                if "recipe" not in item or not item["recipe"]:
                    continue
                    
                # 创建合成表条目
                table = {
                    "count": item.get("output", 1),
                    "machine": item["recipeType"] if "recipeType" in item else "工作台",
                    "materialList": []
                }
                
                # 统计配方中的材料
                material_counts = defaultdict(int)
                for slot in item["recipe"]:
                    if slot and isinstance(slot, dict):
                        material_id = slot["material"]
                        amount = slot.get("amount", 1)
                        material_counts[material_id] += amount
                
                # 将统计结果转换为materialList
                for material_id, count in material_counts.items():
                    table["materialList"].append([material_id, count])
                
                craft_table[item_id] = table
            
            rl.write("sra.log", f"data_loader:已构建合成表，包含 {len(craft_table)} 个配方")
            
            # 初始化物品列表
            item_list = {}
            for item_id, table in craft_table.items():
                item_list[item_id] = table
            
            _crafting_helper = CraftingHelperCore(item_list)
            rl.write("sra.log", "data_loader:全局合成助手初始化完成")
        except Exception as e:
            rl.write("sra.log", f"data_loader:构建合成表时出错: {str(e)}")
            _crafting_helper = None
        
        return _crafting_helper
    
    def get_crafting_helper(self):
        """获取全局合成助手实例"""
        global _crafting_helper
        return _crafting_helper

# 创建单例实例
_data_loader = _DataLoader()

# 提供与之前相同的全局接口
data = _data
base_materials = _base_materials
id_to_name = _id_to_name
all_item_ids = _all_item_ids

# 提供与之前相同的函数接口
def load_data():
    return _data_loader.load_data()

def save_base_materials(new_materials):
    return _data_loader.save_base_materials(new_materials)

def get_base_materials():
    return _data_loader.get_base_materials()

def validate_material_ids(material_ids):
    return _data_loader.validate_material_ids(material_ids)

def get_crafting_helper():
    return _data_loader.get_crafting_helper()

# 在导入模块时自动加载数据
try:
    if not data:
        rl.write("sra.log", "data_loader:自动加载数据...")
        load_data()
except Exception as e:
    rl.write("sra.log", f"data_loader:自动加载数据时出错: {str(e)}")